/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

#ifndef __dylab_ComGfx_h__
#define __dylab_ComGfx_h__

//===========================================================================================
#include <dylab/utils/components/ComponentBase.h>
#include <dylab/utils/containers/VectorContainer.h>
#include <dylab/utils/Colour.h>
#include <dylab/utils/geometry/Plane.h>
#include <dylab/utils/geometry/Vector2.h>
#include <dylab/utils/log/Log.h>
#include <dylab/utils/types/TypeParser.h>
#include <dylab/utils/exceptions/EInvalidArgument.h>
#include <dylab/simulation/ISimulationComponent.h>
#include <dylab/simulation/EventDispatcher.h>

//===========================================================================================
namespace dylab {

    /** Simulation gfx component type.
	@remarks
		This class defines an interface for the simulation gfx component type.
		Components of this type are responsible for implementing the requested gfx driver.
     @warning 
		Never use pointers to the declared interfaces without 
		locking up the whole ComGfx::Instace object!
    */
    class DYLAB_EXPORT ComGfx
        : public ISimulationComponent
        , public ComponentBase<ComGfx>
    {
    public:
		/// The name that acts as an alias of the default gfx entities.
        static const String DEFAULT_NAME;

    public:
        class DYLAB_EXPORT EventDispatcher
            : public dylab::EventDispatcher<GfxEvent>
        {
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the graphics viewport.		
		*/
        class DYLAB_EXPORT IViewport
        {
        public:
            enum {
                DEFAULT_ZORDER = static_cast<uint32_t>(-1)
            };

        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IViewport>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, uint32_t _viewportZOrder = DEFAULT_ZORDER, const String & _windowName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IViewport>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getWindow(/*_windowName*/)->getViewport(_viewportZOrder); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IViewport>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, uint32_t _viewportZOrder = DEFAULT_ZORDER, const String & _windowName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IViewport>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getWindow(/*_windowName*/)->getViewport(_viewportZOrder); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IViewport()
                    { }

            virtual uint32_t getZOrder() const = 0;
            virtual void setBackgroundColour(const Colour & _colour) = 0;
            virtual Vector2 getSize() const = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the triangle 3D-mesh.
		*/
        class DYLAB_EXPORT IMesh
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IMesh>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _meshName)
                    : Instance::ScopedShLock_InternalObj<IMesh>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getMeshManager()->getMesh(_meshName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IMesh>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _meshName)
                    : Instance::ScopedExLock_InternalObj<IMesh>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getMeshManager()->getMesh(_meshName); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IMesh()
                    { }            

            virtual String getName() const = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the IMesh manager.
		*/
        class DYLAB_EXPORT IMeshManager
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IMeshManager>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard)
                    : Instance::ScopedShLock_InternalObj<IMeshManager>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getMeshManager(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IMeshManager>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard)
                    : Instance::ScopedExLock_InternalObj<IMeshManager>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getMeshManager(); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IMeshManager()
                    { }

            virtual IMesh * createMesh(const String & _name) = 0;
            virtual IMesh * getMesh(const String & _name) = 0;
            virtual const IMesh * getMesh(const String & _name) const = 0;
            virtual void destroyMesh(const String & _name) = 0;

            virtual IMesh * createPlane(const String & _name, const Plane & _plane, const Vector2 & _size, 
                                        const Vector2 & _segments, const Vector2 & _tiles) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the scene light.
		*/
        class DYLAB_EXPORT ILight
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<ILight>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _lightName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<ILight>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getLight(_lightName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<ILight>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _lightName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<ILight>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getLight(_lightName); }
            };
            //-----------------------------------------------------------------------------

        public:
            enum type_t
            {
                DIRECTIONAL,
                POINT,
                SPOTLIGHT
            };

        public:
            virtual ~ILight()
                    { }

            virtual String getName() const = 0;
            virtual type_t getType() const = 0;

            virtual void setPosition(const Vector3 & _position) = 0;
            virtual Vector3 getPosition() const = 0;

            virtual void setDirection(const Vector3 & _position) = 0;
            virtual Vector3 getDirection() const = 0;

            virtual void setDiffuseColour(const Colour & _colour) = 0;
            virtual Colour getDiffuseColour() const = 0;

            virtual void setSpecularColour(const Colour & _colour) = 0;
            virtual Colour getSpecularColour() const = 0;

            virtual void setAttenuation(real_t _range, real_t _constant, real_t _linear, real_t _quadratic) = 0;
            virtual void setCastShadows(bool _castShadows) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the scene camera.
		*/
        class DYLAB_EXPORT ICamera
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<ICamera>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _cameraName = DEFAULT_NAME, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<ICamera>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getCamera(_cameraName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<ICamera>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _cameraName = DEFAULT_NAME, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<ICamera>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getCamera(_cameraName); }
            };
            //-----------------------------------------------------------------------------

        public:
            enum polygon_mode_t
            {
                SOLID,
                WIREFRAME,
                POINTS
            };

        public:
            virtual ~ICamera() 
                    { }

            virtual String getName() const = 0;
            virtual void setPosition(const Vector3 & pos) = 0;            

            virtual void move(const Vector3 & pos) = 0;            
            virtual void rotate(real_t yaw, real_t pitch, real_t roll) = 0;
            virtual void lookAt(const Vector3 & target) = 0;

            virtual polygon_mode_t getPolygonMode() const = 0;
            virtual void setPolygonMode(polygon_mode_t _polygonMode) = 0;

            virtual void setNearClipDistance(real_t _distance) = 0;
            virtual void setFarClipDistance(real_t _distance) = 0;
            virtual void setAspectRatio(real_t _ratio) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the application window.
		*/
        class DYLAB_EXPORT IWindow
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IWindow>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _windowName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IWindow>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getWindow(/*_windowName*/); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IWindow>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _windowName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IWindow>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getWindow(/*_windowName*/); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IWindow()
                    { }

            virtual String getName() const = 0;

            virtual void getMetrics(uint32_t & _width, uint32_t & _height, uint32_t & _colourDepth, int32_t & _left, int32_t & _top) const = 0;
            virtual void getStatistics(uint32_t & _lastFPS, uint32_t & _bestFPS, uint32_t & _worstFPS, uint32_t & _triangleCount) const = 0;
            virtual void getPlatformHandle(void * _handle) const = 0;

            virtual void setPosition(const Vector2 & _pos) = 0;

            virtual IViewport * 
                createViewport(uint32_t _zOrder, ICamera * _renderCamera = NULL, 
                               const Vector2 & _position = Vector2::ZERO, const Vector2 & _size = Vector2(1, 1)) = 0;
            virtual IViewport * getViewport(uint32_t _zOrder = IViewport::DEFAULT_ZORDER) = 0;
            virtual const IViewport * getViewport(uint32_t _zOrder = IViewport::DEFAULT_ZORDER) const = 0;
            virtual void destroyViewport(uint32_t _zOrder = IViewport::DEFAULT_ZORDER) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the scene ray query.
		*/
        class DYLAB_EXPORT IRayQuery
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IRayQuery>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _rayName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IRayQuery>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getRayQuery(_rayName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IRayQuery>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _rayName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IRayQuery>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getRayQuery(_rayName); }
            };
            //-----------------------------------------------------------------------------

        public:
			/** This class defines the interface for the ray query result.
			*/
            class DYLAB_EXPORT IResult
            {
            public:
                virtual ~IResult()
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IRayQuery()
                    { }

            virtual String getName() const = 0;
            virtual IResult * execute(uint32_t _screenX, uint32_t _screenY, Vector3 * _intersect = NULL) = 0;        
        };
        //-----------------------------------------------------------------------------
    
    public:
		/** This class defines the interface for the scene object.
		*/
        class DYLAB_EXPORT IObject
            : public IRayQuery::IResult
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IObject>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _objName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IObject>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getObject(_objName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IObject>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _objName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IObject>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getObject(_objName); }
            };
            //-----------------------------------------------------------------------------

        public:
			/** This class defines the interface for the object's user data.
			*/
            class DYLAB_EXPORT IUserData
            {
            public:
                virtual ~IUserData()
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
			/**	This class defines the interface for the object's vertex texture coordinates.
			*/
            class DYLAB_EXPORT TexCoords
            {
            public:
                real_t u, v;
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT PositionBuffer : public VectorContainer<Vector3> { };
            class DYLAB_EXPORT IndexBuffer : public VectorContainer<uint32_t>  { };
            class DYLAB_EXPORT NormalBuffer : public VectorContainer<Vector3> { };
            class DYLAB_EXPORT TexCoordBuffer : public VectorContainer<TexCoords> { };
            class DYLAB_EXPORT ColourBuffer : public VectorContainer<Colour> { };
            //-----------------------------------------------------------------------------

        public:
            enum section_t {
                ST_TRIANGLE_LIST,
                ST_TRIANGLE_STRIP,
                ST_TRIANGLE_FAN,
                ST_LINE_LIST,
                ST_LINE_STRIP,
                ST_POINT_LIST
            };

        public:
            virtual ~IObject()
                    { }

            virtual String getName() const = 0;

            virtual void setDynamic(bool _dynamic) = 0;
            virtual bool isDynamic() const = 0;

            virtual void createSection(const String & _material, section_t _sectionType,
                                        const PositionBuffer & _positions, 
                                        const IndexBuffer & _indices,
                                        const NormalBuffer * _normals = NULL,
                                        const TexCoordBuffer * _texCoords = NULL,
                                        const ColourBuffer * _colours = NULL) = 0;
            virtual void updateSection(uint32_t _section,
                                        const PositionBuffer & _positions, 
                                        const IndexBuffer & _indices,
                                        const NormalBuffer * _normals = NULL,
                                        const TexCoordBuffer * _texCoords = NULL,
                                        const ColourBuffer * _colours = NULL) = 0;
            virtual void changeSectionMaterialName(uint32_t _section, const String & _material) = 0;

            virtual void setRayQueryFlags(uint32_t _flags) = 0;
            virtual uint32_t getRayQueryFlags() const = 0;

            virtual void setCastShadows(bool _castShadows) = 0;
            virtual bool isCastingShadows() const = 0;

            virtual void translate(const Vector3 & _v) = 0;
            virtual void rotate(const Vector3 & _axis, real_t _degrees) = 0;
            virtual void scale(const Vector3 & _scale) = 0;

            virtual void setUserData(IUserData * _userData) = 0;
            virtual IUserData * getUserData() = 0;
        };
        //-----------------------------------------------------------------------------


    public:
		/** This class defines the interface for the scene object pool.
		*/
        class DYLAB_EXPORT IObjectPool
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IObjectPool>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _objPoolName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IObjectPool>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getObjectPool(_objPoolName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IObjectPool>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _objPoolName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IObjectPool>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getObjectPool(_objPoolName); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IObjectPool()
                    { }

            virtual String getName() const = 0;
            virtual IObject * newObject(const String & _name = String::EMPTY) = 0;
            virtual IObject * getObject(const String & _name) = 0;
            virtual void deleteObject(const String & _name) = 0;
            virtual void deleteAllObjects() = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the scene entity.
		*/
        class DYLAB_EXPORT IEntity
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IEntity>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _entityName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IEntity>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getEntity(_entityName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IEntity>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _entityName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IEntity>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getEntity(_entityName); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IEntity()
                    { }

            virtual String getName() const = 0;

            virtual void translate(const Vector3 & _v) = 0;
            virtual void rotate(const Vector3 & _axis, real_t _degrees) = 0;
            virtual void scale(const Vector3 & _scale) = 0;

            virtual void setCastShadows(bool _castShadows) = 0;
            virtual bool isCastingShadows() const = 0;

            virtual void setRayQueryFlags(uint32_t _flags) = 0;
            virtual uint32_t getRayQueryFlags() const = 0;

            virtual void setMaterialName(const String & _material) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the simulation object's model renderer.
		@remarks
			For creating instance of this class is responsible the SimObject::createModelRenderer() method.
		*/
        class DYLAB_EXPORT IModelRenderer
            : public IRayQuery::IResult
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IModelRenderer>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _modelName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IModelRenderer>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getModelRenderer(_modelName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IModelRenderer>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _modelName, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IModelRenderer>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName)->getModelRenderer(_modelName); }
            };
            //-----------------------------------------------------------------------------

        public:
            enum render_t {
                RT_BOUNDARYMESH,
                RT_TETRAHEDRALVOLUME
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IModelRenderer()
                    { }

            virtual String getName() const = 0;
            virtual String getDescription() const = 0;        

            virtual SimObject * getSimObject() = 0;

            virtual void setMaterialName(const String & _material) = 0;
            virtual String getMaterialName() const = 0;

            virtual void setRenderType(render_t _renderType) = 0;
            virtual render_t getRenderType() const = 0;

            virtual void setCastShadows(bool _castShadows) = 0;
            virtual bool isCastingShadows() const = 0;

            virtual void translate(const Vector3 & _v) = 0;
            virtual void rotate(const Vector3 & _axis, real_t _degrees) = 0;
            virtual void scale(const Vector3 & _scale) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the simulation scene.
		*/
        class DYLAB_EXPORT IScene
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IScene>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IScene>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IScene>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _sceneName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IScene>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getScene(_sceneName); }
            };
            //-----------------------------------------------------------------------------

        public:
			/// The type of the shadow technique.
            enum shadow_t
            {
                ST_NONE,
                ST_STENCIL_MODULATIVE,
                ST_STENCIL_ADDITIVE,
                ST_TEXTURE_MODULATIVE,
                ST_TEXTURE_ADDITIVE
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IScene()
                    { }

            virtual String getName() const = 0;

            virtual ICamera * createCamera(const String & _name) = 0;
            virtual ICamera * getCamera(const String & _name = DEFAULT_NAME) = 0;
            virtual const ICamera * getCamera(const String & _name = DEFAULT_NAME) const = 0;
            virtual void destroyCamera(const String & _name = DEFAULT_NAME) = 0;

            virtual ILight * createLight(const String & _name, ILight::type_t _type) = 0;
            virtual ILight * getLight(const String & _name) = 0;
            virtual const ILight * getLight(const String & _name) const = 0;
            virtual void destroyLight(const String & _name) = 0;

            virtual IObject * createObject(const String & _name) = 0;
            virtual IObject * getObject(const String & _name) = 0;
            virtual const IObject * getObject(const String & _name) const = 0;
            virtual IObject * findObject(const String & _name) = 0;
            virtual void destroyObject(const String & _name) = 0;

            virtual IObjectPool * createObjectPool(const String & _name, uint32_t _maxObjects) = 0;
            virtual IObjectPool * getObjectPool(const String & _name) = 0;
            virtual const IObjectPool * getObjectPool(const String & _name) const = 0;
            virtual void destroyObjectPool(const String & _name) = 0;

            virtual IEntity * createEntity(const String & _name, const String & _meshName) = 0;
            virtual IEntity * getEntity(const String & _name) = 0;
            virtual const IEntity * getEntity(const String & _name) const = 0;
            virtual void destroyEntity(const String & _name) = 0;

            virtual IRayQuery * createRayQuery(const String & _name, uint32_t _queryFlags, 
                                               ICamera * _usedCamera = NULL, IViewport * _targetViewport = NULL) = 0;
            virtual IRayQuery * getRayQuery(const String & _name) = 0;
            virtual const IRayQuery * getRayQuery(const String & _name) const = 0;
            virtual void destroyRayQuery(const String & _name) = 0;

            virtual IModelRenderer * createModelRenderer(const String & _name, const String & _materialName, SimObject * _parentSimObject) = 0;
            virtual IModelRenderer * getModelRenderer(const String & _name) = 0;
            virtual const IModelRenderer * getModelRenderer(const String & _name) const = 0;
            virtual IModelRenderer * findModelRenderer(const String & _name) = 0;
            virtual void destroyModelRenderer(const String & _name) = 0;

            virtual void setAmbientLight(const Colour & _light) = 0;
            virtual Colour getAmbientLight() const = 0;

            virtual void setShadowType(shadow_t _shadowType) = 0;
            virtual shadow_t getShadowType() const = 0;

            virtual void showBoundingBoxes(bool _show) = 0;
            virtual bool areBoundingBoxesVisible() const = 0;
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the graphics gui system.
		*/
        class DYLAB_EXPORT IGuiSystem
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IGuiSystem>
            {
            public:
                ScopedShLock(const Instance * _simGfxGuard, const String & _guiSysName = DEFAULT_NAME)
                    : Instance::ScopedShLock_InternalObj<IGuiSystem>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getGuiSystem(_guiSysName); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// exclussiv escope lock with direct interface access
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IGuiSystem>
            {
            public:
                ScopedExLock(Instance * _simGfxGuard, const String & _guiSysName = DEFAULT_NAME)
                    : Instance::ScopedExLock_InternalObj<IGuiSystem>(_simGfxGuard)
                        { mInternalObjPtr = mObjectPtr->getGuiSystem(_guiSysName); }
            };
            //-----------------------------------------------------------------------------

        public:
            virtual ~IGuiSystem()
                    { }
            
            virtual String getName() const = 0;

            virtual void setMousePosition(const Vector2  & _relPos) = 0;
            virtual void setMouseImage(const String & _fileName) = 0;
            virtual void showMouse(bool _visible) = 0;
            virtual bool isMouseVisible() const = 0;            

            virtual void showGui(const String & _name, bool _show) = 0;
            virtual bool isGuiVisible(const String & _name) const = 0;

            virtual void setGuiElementCaption(const String & _elemName, const String & _caption) = 0;
        };
        //-----------------------------------------------------------------------------

    public:
        ComGfx(const String & _componentName);
        virtual ~ComGfx();

        virtual IWindow * createWindow(const String & _title) = 0;
        virtual IWindow * getWindow() = 0;
        virtual const IWindow * getWindow() const = 0;

        virtual IScene * createScene(const String & _name) = 0;
        virtual IScene * getScene(const String & _name = DEFAULT_NAME) = 0;
        virtual const IScene * getScene(const String & _name = DEFAULT_NAME) const = 0;
        virtual void renderScene(const String & _name = DEFAULT_NAME) = 0;
        virtual void destroyScene(const String & _name = DEFAULT_NAME) = 0;

        virtual IGuiSystem * createGuiSystem(const String & _name, IWindow * _parentWindow = NULL, IScene * _parentScene = NULL) = 0;
        virtual IGuiSystem * getGuiSystem(const String & _name = DEFAULT_NAME) = 0;
        virtual const IGuiSystem * getGuiSystem(const String & _name = DEFAULT_NAME) const = 0;
        virtual void destroyGuiSystem(const String & _name = DEFAULT_NAME) = 0;

        virtual IMeshManager * getMeshManager() = 0;
        virtual const IMeshManager * getMeshManager() const = 0;

        virtual uint32_t getCurrentFrameNumber() const = 0;        
    };

    //===========================================================================================
    template <>
        inline ComGfx::IScene::shadow_t TypeParser::parse(const String & _string)
            { 
                if (_string == "none")
                    return ComGfx::IScene::ST_NONE;
                else if (_string == "stencilModulative")
                    return ComGfx::IScene::ST_STENCIL_MODULATIVE;
                else if (_string == "stencilAdditive")
                    return ComGfx::IScene::ST_STENCIL_ADDITIVE;
                else if (_string == "textureModulative")
                    return ComGfx::IScene::ST_TEXTURE_MODULATIVE;
                else if (_string == "textureAdditive")
                    return ComGfx::IScene::ST_TEXTURE_ADDITIVE;    
                else throw EInvalidArgument(String::fmt("Invalid shadow type format: '%1%'", _string));                
            }
    template <>
        inline ComGfx::IScene::shadow_t TypeParser::parse(const String & _string, const ComGfx::IScene::shadow_t & _defaultValue)
            {
                try { return TypeParser::parse<ComGfx::IScene::shadow_t>(_string); }
                catch (EInvalidFormat &) { return _defaultValue; }
            }
    template <>
        inline String String::fmt(const ComGfx::IScene::shadow_t & _value)
            { 
                switch (_value)
                {
                case ComGfx::IScene::ST_NONE:                
                    return "none";                
                case ComGfx::IScene::ST_STENCIL_MODULATIVE:
                    return "stencilModulative";
                case ComGfx::IScene::ST_STENCIL_ADDITIVE:
                    return "stencilAdditive";
                case ComGfx::IScene::ST_TEXTURE_MODULATIVE:
                    return "textureModulative";
                case ComGfx::IScene::ST_TEXTURE_ADDITIVE:
                    return "textureAdditive";
                default:
                    throw EInvalidArgument(String::fmt("Invalid shadow enumeration value: '%1%'", static_cast<uint32_t>(_value)));
                }
            }

    //===========================================================================================
    template <>
        inline ComGfx::ILight::type_t TypeParser::parse(const String & _string)
            { 
                if (_string == "directional")
                    return ComGfx::ILight::DIRECTIONAL;
                else if (_string == "point")
                    return ComGfx::ILight::POINT;
                else if (_string == "spot")
                    return ComGfx::ILight::SPOTLIGHT;
                else throw EInvalidArgument(String::fmt("Invalid light type format: '%1%'", _string));                
            }
    template <>
        inline ComGfx::ILight::type_t TypeParser::parse(const String & _string, const ComGfx::ILight::type_t & _defaultValue)
            {
                try { return TypeParser::parse<ComGfx::ILight::type_t>(_string); }
                catch (EInvalidFormat &) { return _defaultValue; }
            }
    template <>
        inline String String::fmt(const ComGfx::ILight::type_t & _value)
            { 
                switch (_value)
                {
                case ComGfx::ILight::DIRECTIONAL:                
                    return "directional";                
                case ComGfx::ILight::POINT:
                    return "point";
                case ComGfx::ILight::SPOTLIGHT:
                    return "spotLight";
                default:
                    throw EInvalidArgument(String::fmt("Invalid light type enumeration value: '%1%'", static_cast<uint32_t>(_value)));
                }
            }

    //===========================================================================================
    template <>
        inline ComGfx::IModelRenderer::render_t TypeParser::parse(const String & _string)
            { 
                if (_string == "boundaryMesh")
                    return ComGfx::IModelRenderer::RT_BOUNDARYMESH;
                else if (_string == "tetrahedralVolume")
                    return ComGfx::IModelRenderer::RT_TETRAHEDRALVOLUME;
                else throw EInvalidArgument(String::fmt("Invalid render type format: '%1%'", _string));                
            }
    template <>
        inline ComGfx::IModelRenderer::render_t TypeParser::parse(const String & _string, const ComGfx::IModelRenderer::render_t & _defaultValue)
            {
                try { return TypeParser::parse<ComGfx::IModelRenderer::render_t>(_string); }
                catch (EInvalidFormat &) { return _defaultValue; }
            }
    template <>
        inline String String::fmt(const ComGfx::IModelRenderer::render_t & _value)
            { 
                switch (_value)
                {                
                case ComGfx::IModelRenderer::RT_BOUNDARYMESH:
                    return "boundaryMesh";                
                case ComGfx::IModelRenderer::RT_TETRAHEDRALVOLUME:
                    return "tetrahedralVolume";
                default:
                    throw EInvalidArgument(String::fmt("Invalid render type enumeration value: '%1%'", static_cast<uint32_t>(_value)));
                }
            }
}
//===========================================================================================
#endif // __dylab_ComGfx_h__
